
package com.hlkj.pay.service.order.impl;
/*
 * Hlpay-Plus aggregate payment system.
 * Copyright (c) 2024-2025 Hlpay Team Copyright has the right of final interpretation.
 */

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.hlkj.framework.common.pojo.PageResult;
import com.hlkj.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.hlkj.framework.mybatis.core.query.QueryWrapperX;
import com.hlkj.framework.mybatis.core.utils.MyBatisUtils;
import com.hlkj.pay.dto.merchant.MerchantAccessInfoPageQueryDto;
import com.hlkj.pay.dto.order.OrderStatisticsDto;
import com.hlkj.pay.dto.order.OrderStatisticsGroupDto;
import com.hlkj.pay.dto.order.OrderStatisticsQueryDto;
import com.hlkj.pay.enums.CommonEnum;
import com.hlkj.pay.enums.PayOrderEnums;
import com.hlkj.pay.infrastructure.mapper.order.OrderStatisticsMapper;
import com.hlkj.pay.infrastructure.model.order.OrderStatisticsDO;
import com.hlkj.pay.service.CommonSnFilterService;
import com.hlkj.pay.service.order.IOrderStatisticsService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author HlpayTeam
 * @date 2024/11/08 13:26
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class OrderStatisticsServiceImpl extends CommonSnFilterService implements IOrderStatisticsService {

    private final OrderStatisticsMapper orderStatisticsMapper;

    @Override
    public PageResult<OrderStatisticsDO> queryPage(OrderStatisticsQueryDto orderStatisticsQueryDto) {
        return orderStatisticsMapper.selectPage(orderStatisticsQueryDto, buildWrapper(orderStatisticsQueryDto));
    }

    @Override
    public List<OrderStatisticsDO> queryStatistics(OrderStatisticsQueryDto orderStatisticsQueryDto) {
        return orderStatisticsMapper.selectList(buildWrapper(orderStatisticsQueryDto));
    }

    @Override
    public void deleteByIds(List<Long> ids, String remark) {
        OrderStatisticsDO orderStatisticsDO = new OrderStatisticsDO();
        orderStatisticsDO.setRemark(remark);
        orderStatisticsDO.setDeleteFlag(true);
        OrderStatisticsQueryDto orderStatisticsQueryDto = new OrderStatisticsQueryDto();
        orderStatisticsQueryDto.setIds(ids);
        orderStatisticsMapper.update(orderStatisticsDO, buildWrapper(orderStatisticsQueryDto));
        orderStatisticsMapper.deleteBatchIds(ids);
    }

    @Override
    public void addStatisticsList(List<OrderStatisticsDO> addStatisticsList) {
        orderStatisticsMapper.insertBatch(addStatisticsList);
    }

    @Override
    public OrderStatisticsDO queryOne(String sn, Integer type, String relationId, Long time) {
        OrderStatisticsQueryDto orderStatisticsQueryDto = new OrderStatisticsQueryDto();
        orderStatisticsQueryDto.setSn(sn);
        orderStatisticsQueryDto.setTime(time);
        orderStatisticsQueryDto.setType(type);
        orderStatisticsQueryDto.setRelationId(relationId);
        return orderStatisticsMapper.selectOne(buildWrapper(orderStatisticsQueryDto));
    }

    @Override
    public void updateStatistics(OrderStatisticsDO orderStatisticsDO) {
        orderStatisticsDO.setUpdateTime(System.currentTimeMillis());
        orderStatisticsMapper.updateStatistics(orderStatisticsDO);
    }

    @Override
    public OrderStatisticsDO addStatistics(OrderStatisticsDO orderStatisticsDO) {
        orderStatisticsMapper.insert(orderStatisticsDO);
        return orderStatisticsDO;
    }

    @Override
    public OrderStatisticsDO queryOrderStatistics(OrderStatisticsQueryDto orderStatisticsQueryDto) {
        return orderStatisticsMapper.queryStatistics(orderStatisticsQueryDto);
    }

    @Override
    public List<OrderStatisticsDO> queryList(String sn, Integer type, String relationId, Set<Long> timeKeys) {
        OrderStatisticsQueryDto orderStatisticsQueryDto = new OrderStatisticsQueryDto();
        orderStatisticsQueryDto.setSn(sn);
        orderStatisticsQueryDto.setType(type);
        orderStatisticsQueryDto.setRelationId(relationId);
        orderStatisticsQueryDto.setTimes(timeKeys);
        return orderStatisticsMapper.selectList(buildWrapper(orderStatisticsQueryDto));
    }

    @Override
    public PageResult<OrderStatisticsGroupDto> queryTranPage(OrderStatisticsQueryDto orderStatisticsQueryDto) {
        if (StringUtils.hasText(orderStatisticsQueryDto.getSortBy())) {
            if (StringUtils.hasText(orderStatisticsQueryDto.getSortBy())) {
                String sortBy = orderStatisticsQueryDto.getSortBy().chars().mapToObj(c -> (char)c).map(c -> Character.isUpperCase(c) ? "_" + Character.toLowerCase(c) : String.valueOf(c))
                        .collect(Collectors.joining());
                if ("desc".equals(orderStatisticsQueryDto.getSort()))
                    orderStatisticsQueryDto.setSortingFields(sortBy + "-");
                else orderStatisticsQueryDto.setSortingFields(sortBy + "+");
            }
        } else
            orderStatisticsQueryDto.setSortingFields("time");
        IPage<OrderStatisticsGroupDto> mpPage = MyBatisUtils.buildPage(orderStatisticsQueryDto);
        // queryWrapper.orderByDesc("a.id");
        orderStatisticsQueryDto.setType(PayOrderEnums.ORDER_STATISTICS_TYPE.SN.getCode());
        orderStatisticsMapper.queryGroupPage(mpPage, buildGroupWrapper(orderStatisticsQueryDto));
        return new PageResult(mpPage.getRecords(), mpPage.getTotal(), mpPage.getCurrent(), mpPage.getSize(), mpPage.getPages());
    }

    @Override
    public List<OrderStatisticsGroupDto> queryTranList(OrderStatisticsQueryDto orderStatisticsQueryDto) {
        orderStatisticsQueryDto.setSortingFields("time desc");
        orderStatisticsQueryDto.setType(PayOrderEnums.ORDER_STATISTICS_TYPE.SN.getCode());
        return orderStatisticsMapper.queryGroupPage(buildGroupWrapper(orderStatisticsQueryDto));
    }

    @Override
    public PageResult<OrderStatisticsDO> queryAgentPage(OrderStatisticsQueryDto orderStatisticsQueryDto) {
        if (StringUtils.hasText(orderStatisticsQueryDto.getSortBy())) {
            if (StringUtils.hasText(orderStatisticsQueryDto.getSortBy())) {
                String sortBy = orderStatisticsQueryDto.getSortBy().chars().mapToObj(c -> (char)c).map(c -> Character.isUpperCase(c) ? "_" + Character.toLowerCase(c) : String.valueOf(c))
                        .collect(Collectors.joining());
                if ("desc".equals(orderStatisticsQueryDto.getSort()))
                    orderStatisticsQueryDto.setSortingFields(sortBy + "-");
                else orderStatisticsQueryDto.setSortingFields(sortBy + "+");
            }
        } else
            orderStatisticsQueryDto.setSortingFields("relation_id");
        IPage<MerchantAccessInfoPageQueryDto> mpPage = MyBatisUtils.buildPage(orderStatisticsQueryDto);
        orderStatisticsQueryDto.setType(PayOrderEnums.ORDER_STATISTICS_TYPE.SN.getCode());
        orderStatisticsMapper.queryAgentPage(mpPage, buildJoinWrapper(orderStatisticsQueryDto));
        return new PageResult(mpPage.getRecords(), mpPage.getTotal(), mpPage.getCurrent(), mpPage.getSize(), mpPage.getPages());
    }

    @Override
    public List<OrderStatisticsDO> queryAgentList(OrderStatisticsQueryDto orderStatisticsQueryDto) {
        orderStatisticsQueryDto.setSortingFields("relation_id");
        orderStatisticsQueryDto.setType(PayOrderEnums.ORDER_STATISTICS_TYPE.SN.getCode());
        return orderStatisticsMapper.queryAgentPage(buildJoinWrapper(orderStatisticsQueryDto));
    }

    @Override
    public PageResult<OrderStatisticsDto> queryChannelCodePage(OrderStatisticsQueryDto orderStatisticsQueryDto) {
        if (StringUtils.hasText(orderStatisticsQueryDto.getSortBy())) {
            if (StringUtils.hasText(orderStatisticsQueryDto.getSortBy())) {
                String sortBy = orderStatisticsQueryDto.getSortBy().chars().mapToObj(c -> (char)c).map(c -> Character.isUpperCase(c) ? "_" + Character.toLowerCase(c) : String.valueOf(c))
                        .collect(Collectors.joining());
                if ("desc".equals(orderStatisticsQueryDto.getSort()))
                    orderStatisticsQueryDto.setSortingFields(sortBy + "-");
                else orderStatisticsQueryDto.setSortingFields(sortBy + "+");
            }
        } else
            orderStatisticsQueryDto.setSortingFields("relation_id");
        IPage<MerchantAccessInfoPageQueryDto> mpPage = MyBatisUtils.buildPage(orderStatisticsQueryDto);
        orderStatisticsQueryDto.setType(PayOrderEnums.ORDER_STATISTICS_TYPE.CHANNEL_CODE.getCode());
        orderStatisticsMapper.queryChannelCodePage(mpPage, buildJoinWrapper(orderStatisticsQueryDto));
        return new PageResult(mpPage.getRecords(), mpPage.getTotal(), mpPage.getCurrent(), mpPage.getSize(), mpPage.getPages());
    }

    @Override
    public List<OrderStatisticsDto> queryChannelCodeList(OrderStatisticsQueryDto orderStatisticsQueryDto) {
        orderStatisticsQueryDto.setSortingFields("relation_id");
        orderStatisticsQueryDto.setType(PayOrderEnums.ORDER_STATISTICS_TYPE.CHANNEL_CODE.getCode());
        return orderStatisticsMapper.queryChannelCodePage(buildJoinWrapper(orderStatisticsQueryDto));
    }

    @Override
    public PageResult<OrderStatisticsDto> queryAutCodePage(OrderStatisticsQueryDto orderStatisticsQueryDto) {
        if (StringUtils.hasText(orderStatisticsQueryDto.getSortBy())) {
            if (StringUtils.hasText(orderStatisticsQueryDto.getSortBy())) {
                String sortBy = orderStatisticsQueryDto.getSortBy().chars().mapToObj(c -> (char)c).map(c -> Character.isUpperCase(c) ? "_" + Character.toLowerCase(c) : String.valueOf(c))
                        .collect(Collectors.joining());
                if ("desc".equals(orderStatisticsQueryDto.getSort()))
                    orderStatisticsQueryDto.setSortingFields(sortBy + "-");
                else orderStatisticsQueryDto.setSortingFields(sortBy + "+");
            }
        } else
            orderStatisticsQueryDto.setSortingFields("relation_id");
        IPage<MerchantAccessInfoPageQueryDto> mpPage = MyBatisUtils.buildPage(orderStatisticsQueryDto);
        orderStatisticsQueryDto.setType(PayOrderEnums.ORDER_STATISTICS_TYPE.AUT_CODE.getCode());
        orderStatisticsMapper.queryAutCodePage(mpPage, buildJoinWrapper(orderStatisticsQueryDto));
        return new PageResult(mpPage.getRecords(), mpPage.getTotal(), mpPage.getCurrent(), mpPage.getSize(), mpPage.getPages());
    }

    @Override
    public List<OrderStatisticsDto> queryAutCodeList(OrderStatisticsQueryDto orderStatisticsQueryDto) {
        orderStatisticsQueryDto.setSortingFields("relation_id");
        orderStatisticsQueryDto.setType(PayOrderEnums.ORDER_STATISTICS_TYPE.AUT_CODE.getCode());
        return orderStatisticsMapper.queryAutCodePage(buildJoinWrapper(orderStatisticsQueryDto));
    }

    @Override
    public void deleteByTime(long startQueryTime, String sn, String remark) {
        OrderStatisticsQueryDto orderStatisticsQueryDto = new OrderStatisticsQueryDto();
        orderStatisticsQueryDto.setTime(startQueryTime);
        orderStatisticsQueryDto.setSn(sn);
        List<OrderStatisticsDO> statisticsList = queryStatistics(orderStatisticsQueryDto);
        List<Long> ids = statisticsList.stream().map(statisticsDO -> statisticsDO.getId()).collect(Collectors.toList());
        orderStatisticsMapper.updateRemark(ids, remark);
    }

    @Override
    public PageResult<OrderStatisticsDO> queryCommonPage(OrderStatisticsQueryDto orderStatisticsQueryDto) {
        if (StringUtils.hasText(orderStatisticsQueryDto.getSortBy())) {
            if (StringUtils.hasText(orderStatisticsQueryDto.getSortBy())) {
                String sortBy = orderStatisticsQueryDto.getSortBy().chars().mapToObj(c -> (char)c).map(c -> Character.isUpperCase(c) ? "_" + Character.toLowerCase(c) : String.valueOf(c))
                        .collect(Collectors.joining());
                if ("desc".equals(orderStatisticsQueryDto.getSort()))
                    orderStatisticsQueryDto.setSortingFields(sortBy + "-");
                else orderStatisticsQueryDto.setSortingFields(sortBy + "+");
            }
        } else
            orderStatisticsQueryDto.setSortingFields("relation_id");
        IPage<MerchantAccessInfoPageQueryDto> mpPage = MyBatisUtils.buildPage(orderStatisticsQueryDto);
        orderStatisticsMapper.queryCommonPage(mpPage, buildWrapper(orderStatisticsQueryDto));
        return new PageResult(mpPage.getRecords(), mpPage.getTotal(), mpPage.getCurrent(), mpPage.getSize(), mpPage.getPages());
    }

    @Override
    public List<OrderStatisticsDO> queryCommonList(OrderStatisticsQueryDto orderStatisticsQueryDto) {
        orderStatisticsQueryDto.setSortingFields("relation_id");
        return orderStatisticsMapper.queryCommonPage(buildWrapper(orderStatisticsQueryDto));
    }

    @Override
    public PageResult<OrderStatisticsDto> queryMchChannelCodePage(OrderStatisticsQueryDto orderStatisticsQueryDto) {
        if (StringUtils.hasText(orderStatisticsQueryDto.getSortBy())) {
            if (StringUtils.hasText(orderStatisticsQueryDto.getSortBy())) {
                String sortBy = orderStatisticsQueryDto.getSortBy().chars().mapToObj(c -> (char)c).map(c -> Character.isUpperCase(c) ? "_" + Character.toLowerCase(c) : String.valueOf(c))
                        .collect(Collectors.joining());
                if ("desc".equals(orderStatisticsQueryDto.getSort()))
                    orderStatisticsQueryDto.setSortingFields(sortBy + "-");
                else orderStatisticsQueryDto.setSortingFields(sortBy + "+");
            }
        } else
            orderStatisticsQueryDto.setSortingFields("relation_id");
        IPage<MerchantAccessInfoPageQueryDto> mpPage = MyBatisUtils.buildPage(orderStatisticsQueryDto);
        orderStatisticsQueryDto.setType(PayOrderEnums.ORDER_STATISTICS_TYPE.MCH_CHANNEL_CODE.getCode());
        orderStatisticsMapper.queryMchChannelCodePage(mpPage, buildJoinWrapper(orderStatisticsQueryDto));
        return new PageResult(mpPage.getRecords(), mpPage.getTotal(), mpPage.getCurrent(), mpPage.getSize(), mpPage.getPages());
    }

    @Override
    public List<OrderStatisticsDto> queryMchChannelCodeList(OrderStatisticsQueryDto orderStatisticsQueryDto) {
        orderStatisticsQueryDto.setSortingFields("relation_id");
        orderStatisticsQueryDto.setType(PayOrderEnums.ORDER_STATISTICS_TYPE.MCH_CHANNEL_CODE.getCode());
        return orderStatisticsMapper.queryMchChannelCodePage(buildJoinWrapper(orderStatisticsQueryDto));
    }

    /**
     * 查询条件封装
     *
     * @param orderStatisticsQueryDto
     * @return
     */
    LambdaQueryWrapper<OrderStatisticsDO> buildWrapper(OrderStatisticsQueryDto orderStatisticsQueryDto) {
        filterSn(orderStatisticsQueryDto);
        LambdaQueryWrapperX<OrderStatisticsDO> queryWrapper = new LambdaQueryWrapperX<>();
        queryWrapper.eqIfPresent(OrderStatisticsDO::getDeleteFlag, CommonEnum.YES_NO_TYPE.NO.getCode());
        queryWrapper.eqIfPresent(OrderStatisticsDO::getType, orderStatisticsQueryDto.getType());
        queryWrapper.eqIfPresent(OrderStatisticsDO::getSn, orderStatisticsQueryDto.getSn());
        queryWrapper.inIfPresent(OrderStatisticsDO::getSn, orderStatisticsQueryDto.getSnList());
        queryWrapper.eqIfPresent(OrderStatisticsDO::getRelationId, orderStatisticsQueryDto.getRelationId());
        queryWrapper.inIfPresent(OrderStatisticsDO::getRelationId, orderStatisticsQueryDto.getRelationIds());
        queryWrapper.inIfPresent(OrderStatisticsDO::getId, orderStatisticsQueryDto.getIds());
        queryWrapper.eqIfPresent(OrderStatisticsDO::getTime, orderStatisticsQueryDto.getTime());
        queryWrapper.inIfPresent(OrderStatisticsDO::getTime, orderStatisticsQueryDto.getTimes());
        queryWrapper.geIfPresent(OrderStatisticsDO::getTime, orderStatisticsQueryDto.getStartQueryTime());
        queryWrapper.leIfPresent(OrderStatisticsDO::getTime, orderStatisticsQueryDto.getEndQueryTime());
        return queryWrapper;
    }

    /**
     * 查询条件封装
     *
     * @param orderStatisticsQueryDto
     * @return
     */
    QueryWrapperX<OrderStatisticsGroupDto> buildGroupWrapper(OrderStatisticsQueryDto orderStatisticsQueryDto) {
        filterSn(orderStatisticsQueryDto);
        QueryWrapperX<OrderStatisticsGroupDto> queryWrapper = new QueryWrapperX<>();
        queryWrapper.eqIfPresent("type", orderStatisticsQueryDto.getType());
        queryWrapper.eqIfPresent("sn", orderStatisticsQueryDto.getSn());
        queryWrapper.inIfPresent("sn", orderStatisticsQueryDto.getSnList());
        queryWrapper.eqIfPresent("time", orderStatisticsQueryDto.getTime());
        queryWrapper.betweenIfPresent("time", orderStatisticsQueryDto.getStartQueryTime(), orderStatisticsQueryDto.getEndQueryTime());
//        queryWrapper.geIfPresent("time", orderStatisticsQueryDto.getStartQueryTime());
//        queryWrapper.leIfPresent("time", orderStatisticsQueryDto.getEndQueryTime());
        queryWrapper.eqIfPresent("statistics_dim", orderStatisticsQueryDto.getQueryType());
        return queryWrapper;
    }

    /**
     * 查询条件封装
     *
     * @param orderStatisticsQueryDto
     * @return
     */
    QueryWrapper<OrderStatisticsDO> buildJoinWrapper(OrderStatisticsQueryDto orderStatisticsQueryDto) {
        filterSn(orderStatisticsQueryDto);
        QueryWrapperX<OrderStatisticsDO> queryWrapper = new QueryWrapperX<>();
        queryWrapper.eq("tos.delete_flag", 0);
        queryWrapper.eqIfPresent("tos.type", orderStatisticsQueryDto.getType());
        queryWrapper.eqIfPresent( "tos.sn", orderStatisticsQueryDto.getSn());
        queryWrapper.inIfPresent( "tos.sn", orderStatisticsQueryDto.getSnList());
        queryWrapper.eqIfPresent("tos.relation_id", orderStatisticsQueryDto.getRelationId());
        queryWrapper.inIfPresent("tos.relation_id", orderStatisticsQueryDto.getRelationIds());
        queryWrapper.geIfPresent( "tos.time", orderStatisticsQueryDto.getStartQueryTime());
        queryWrapper.leIfPresent("tos.time", orderStatisticsQueryDto.getEndQueryTime());
        queryWrapper.eqIfPresent( "tr.sub_mch_id", orderStatisticsQueryDto.getSubMchId());
        queryWrapper.eqIfPresent("tr.super_agent", orderStatisticsQueryDto.getAgentId());
        return queryWrapper;
    }
}
